package services

import (
	"errors"
	"fmt"
	"gitee.com/phpdi/ant-api/entitys"
	"gitee.com/phpdi/ant-api/utils"
	"github.com/astaxie/beego/orm"
	"time"
)

//rbac权限服务
type roleService struct {
}

//角色服务单例对象
var RoleService *roleService
func init()  {
	RoleService=new(roleService)
}


//角色管理
func (this *roleService) List(search entitys.RoleSearchParams) (err error) {

	var roles []entitys.Role

	q := Orm().QueryTable(TableName("role"))
	if search.Name != "" {
		q = q.Filter("name__contains", search.Name)
	}

	_, err = q.Limit(search.PageSize).Offset(search.Offset()).All(&roles)

	search.SetSliceData(roles)

	return
}

//获取角色数据
func (this *roleService) GetRoles(roleIds ...int) (roles []entitys.Role,err error) {

	type Perm_RolePerm struct {
		entitys.Perm
		entitys.RolePerm
	}
	var (
		res []Perm_RolePerm
	)

	roleIds = append(roleIds, 0)
	roleIdStr := utils.Join(roleIds, ",")
	if roleIdStr == "" {
		return
	}

	_, _ = Orm().QueryTable(TableName("role")).Filter("id__in", roleIds).All(&roles)

	qb, _ := orm.NewQueryBuilder("mysql")
	qb.Select("p.id", "p.name", "p.perm_url", "p.perm_tree_id", "rp.role_id", "rp.perm_id").
		From(TableName("perm") + " as p").
		InnerJoin(TableName("role_perm") + " as rp").On("rp.perm_id = p.id").
		Where(fmt.Sprintf("rp.role_id in (%s)", roleIdStr))

	// 执行 SQL 语句
	_, _ = Orm().Raw(qb.String()).QueryRows(&res)

	for k, v := range roles {
		for _, v1 := range res {
			if v.Id == v1.RoleId {
				roles[k].Perms = append(roles[k].Perms, v1.Perm)
			}
		}
	}

	return
}

//获取单条角色信息
func (this *roleService) GetRoleByRoleId(roleId uint32, queryPerm bool) (role entitys.Role, err error) {
	role.Id=roleId
	if err = Orm().Read(&role);err!= nil {
		return
	}

	//查询权限数据
	if queryPerm == true {
		role.Perms ,err= PermService.GetPermsByRoleId(roleId)
	}

	return

}

//角色添加
func (this *roleService) Add(tran *Transactor, role entitys.Role) (roleId int64,err error) {

	err = tran.Transaction(func(o orm.Ormer) error {

		//检查角色名重复
		if _, ok := Repeat(&role, TableName("role"), "Id", "Name"); ok {
			return errors.New("角色名称重复")
		}

		//添加
		role.CreateTime = time.Now()
		role.UpdateTime = time.Now()
		if roleId, err = o.Insert(&role);err != nil {
			return errors.New("添加角色失败")
		}


		return nil
	})

	return
}

//角色编辑
func (this *roleService) Edit(tran *Transactor,role entitys.Role) (err    error) {

	err= tran.Transaction(func(o orm.Ormer) error {

		if role.Id == 0 {
			return errors.New("角色ID缺失.")
		}

		//检查角色名重复
		if _, ok := Repeat(&role, TableName("role"), "Id", "Name"); ok {
			return errors.New("角色名称重复")
		}

		//编辑
		role.UpdateTime = time.Now()
		if _, err = o.Update(&role,utils.GetNotZeroFields(role)...);err != nil {
			return errors.New("编辑角色失败")
		}

		return nil
	})

	if err!= nil {
		//刷新用户权限
		PermService.FlushUserPermsCacheByRoleId(role.Id)
	}

	return err
}


//通过用户Id获取角色信息
func (this *roleService) GetRolesByUserId(userId uint32) (roles []entitys.Role,err error) {

	//构建查询器
	qb, _ := orm.NewQueryBuilder("mysql")
	qb.Select("r.id", "r.name", "r.desc", "r.enable", "r.create_time", "r.update_time").
		From(TableName("role") + " as r").
		InnerJoin(TableName("role_user") + " as ru").On("r.id = ru.role_id").
		Where(fmt.Sprintf("ru.user_id=%d", userId))

	// 执行 SQL 语句
	_, err = Orm().Raw(qb.String()).QueryRows(&roles)

	return
}

//绑定角色的权限
func (this *roleService) BindRolePerms(tran *Transactor, roleId uint32, permIds ...uint32) error {
	return tran.Transaction(func(o orm.Ormer) error {

		//删除绑定关系
		if _, err := o.QueryTable(TableName("role_perm")).Filter("role_id", roleId).Delete();err != nil {
			return err
		}

		for _, permId := range permIds {
			item := entitys.RolePerm{
				RoleId: roleId,
				PermId: permId,
			}

			if _, err:= o.Insert(&item);err != nil {
				return errors.New("绑定权限失败")
			}

		}

		return nil
	})
}

//绑定用户角色,支持绑定多个角色
func (this *roleService) BindUserRoles(tran *Transactor, userId uint32, roleIds ...uint32) (err error) {


	err = tran.Transaction(func(o orm.Ormer) error {
		//删除绑定关系
		if _, err = o.QueryTable(TableName("role_user")).Filter("user_id", userId).Delete();err != nil {
			return nil
		}

		for _, roleId := range roleIds {
			item := entitys.RoleUser{
				RoleId: roleId,
				UserId: userId,
			}

			_, err := o.Insert(&item)

			if err != nil {
				return errors.New("绑定角色失败")
			}

		}

		return nil
	})

	if err != nil {
		//刷新用户权限
		PermService.FlushUserPermsCacheByUserId(userId)
	}

	return err
}
